package com.rickpan.controller;

import com.rickpan.dto.common.ApiResponse;
import com.rickpan.dto.request.UploadInitRequest;
import com.rickpan.dto.request.MergeChunksRequest;
import com.rickpan.dto.response.UploadInitResponse;
import com.rickpan.dto.response.ChunkUploadResponse;
import com.rickpan.dto.response.FileInfoDTO;
import com.rickpan.entity.FileInfo;
import com.rickpan.service.ChunkUploadService;
import com.rickpan.service.FileManagementService;
import com.rickpan.utils.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

/**
 * 文件上传控制器
 * 处理文件上传相关的HTTP请求
 */
@RestController
@RequestMapping("/api/files")
public class FileUploadController {
    
    private static final Logger logger = LoggerFactory.getLogger(FileUploadController.class);
    
    @Autowired
    private ChunkUploadService chunkUploadService;
    
    @Autowired
    private FileManagementService fileManagementService;
    
    /**
     * 初始化上传会话
     * POST /api/files/upload/init
     */
    @PostMapping("/upload/init")
    public ResponseEntity<ApiResponse<UploadInitResponse>> initUpload(
            @RequestBody UploadInitRequest request) {
        
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("用户 {} 初始化上传: {}", userId, request.getFileName());
            
            // 验证请求参数
            validateUploadInitRequest(request);
            
            // 初始化上传会话
            UploadInitResponse response = chunkUploadService.initUpload(userId, request);
            
            logger.info("上传会话初始化成功: uploadId={}, needUpload={}", 
                       response.getUploadId(), response.isNeedUpload());
            
            return ResponseEntity.ok(ApiResponse.success(response));
            
        } catch (Exception e) {
            logger.error("初始化上传失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("初始化上传失败: " + e.getMessage()));
        }
    }
    
    /**
     * 上传分片
     * POST /api/files/upload/chunk/{uploadId}/{chunkIndex}
     */
    @PostMapping("/upload/chunk/{uploadId}/{chunkIndex}")
    public ResponseEntity<ApiResponse<ChunkUploadResponse>> uploadChunk(
            @PathVariable String uploadId,
            @PathVariable Integer chunkIndex,
            @RequestParam("chunk") MultipartFile chunk,
            @RequestParam("chunkMd5") String chunkMd5) {
        
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.debug("用户 {} 上传分片: uploadId={}, chunkIndex={}, size={}", 
                        userId, uploadId, chunkIndex, chunk.getSize());
            
            // 验证分片参数
            validateChunkUpload(uploadId, chunkIndex, chunk, chunkMd5);
            
            // 上传分片
            ChunkUploadResponse response = chunkUploadService.uploadChunk(
                    userId, uploadId, chunkIndex, chunk, chunkMd5);
            
            logger.debug("分片上传成功: uploadId={}, chunkIndex={}, progress={}%", 
                        uploadId, chunkIndex, response.getProgress());
            
            return ResponseEntity.ok(ApiResponse.success(response));
            
        } catch (Exception e) {
            logger.error("分片上传失败: uploadId={}, chunkIndex={}", uploadId, chunkIndex, e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("分片上传失败: " + e.getMessage()));
        }
    }
    
    /**
     * 合并分片
     * POST /api/files/upload/merge
     */
    @PostMapping("/upload/merge")
    public ResponseEntity<ApiResponse<FileInfoDTO>> mergeChunks(
            @RequestBody MergeChunksRequest request) {

        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("用户 {} 合并分片: uploadId={}, fileName={}",
                       userId, request.getUploadId(), request.getFileName());

            // 验证合并请求
            validateMergeRequest(request);

            // 合并分片并创建文件记录
            FileInfo fileInfo = chunkUploadService.mergeChunks(userId, request);

            logger.info("分片合并成功: fileId={}, fileName={}, size={}",
                       fileInfo.getId(), fileInfo.getOriginalName(), fileInfo.getFileSize());

            return ResponseEntity.ok(ApiResponse.success(FileInfoDTO.from(fileInfo)));
            
        } catch (Exception e) {
            logger.error("合并分片失败: uploadId={}", request.getUploadId(), e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("合并分片失败: " + e.getMessage()));
        }
    }
    
    /**
     * 取消上传
     * DELETE /api/files/upload/{uploadId}
     */
    @DeleteMapping("/upload/{uploadId}")
    public ResponseEntity<ApiResponse<Void>> cancelUpload(@PathVariable String uploadId) {
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("用户 {} 取消上传: uploadId={}", userId, uploadId);
            
            chunkUploadService.cancelUpload(userId, uploadId);
            
            return ResponseEntity.ok(ApiResponse.<Void>success(null, "上传已取消"));
            
        } catch (Exception e) {
            logger.error("取消上传失败: uploadId={}", uploadId, e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("取消上传失败: " + e.getMessage()));
        }
    }



    /**
     * 获取上传进度
     * GET /api/files/upload/{uploadId}/progress
     */
    @GetMapping("/upload/{uploadId}/progress")
    public ResponseEntity<ApiResponse<ChunkUploadResponse>> getUploadProgress(
            @PathVariable String uploadId) {
        
        try {
            Long userId = SecurityUtils.getCurrentUserId();
            ChunkUploadResponse progress = chunkUploadService.getUploadProgress(userId, uploadId);
            
            return ResponseEntity.ok(ApiResponse.success(progress));
            
        } catch (Exception e) {
            logger.error("获取上传进度失败: uploadId={}", uploadId, e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("获取上传进度失败: " + e.getMessage()));
        }
    }
    
    /**
     * 简单文件上传（非分片）
     * POST /api/files/upload/simple
     */
    @PostMapping("/upload/simple")
    public ResponseEntity<ApiResponse<FileInfoDTO>> simpleUpload(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "parentId", required = false) Long parentId) {

        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("用户 {} 简单上传: fileName={}, size={}",
                       userId, file.getOriginalFilename(), file.getSize());

            // 验证文件
            if (file.isEmpty()) {
                return ResponseEntity.badRequest()
                        .body(ApiResponse.error("文件不能为空"));
            }

            // 上传文件
            FileInfo fileInfo = fileManagementService.uploadFile(userId, file, parentId);

            logger.info("简单上传成功: fileId={}, fileName={}",
                       fileInfo.getId(), fileInfo.getOriginalName());

            return ResponseEntity.ok(ApiResponse.success(FileInfoDTO.from(fileInfo)));

        } catch (Exception e) {
            logger.error("简单上传失败", e);
            return ResponseEntity.badRequest()
                    .body(ApiResponse.error("上传失败: " + e.getMessage()));
        }
    }

    /**
     * 带传输记录的文件上传
     * POST /api/files/upload/with-transfer
     */
    @PostMapping("/upload/with-transfer")
    public ResponseEntity<ApiResponse<FileInfoDTO>> uploadWithTransfer(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "parentId", required = false) Long parentId,
            @RequestParam(value = "sessionId", required = false) String sessionId) {

        try {
            Long userId = SecurityUtils.getCurrentUserId();
            logger.info("用户 {} 带传输记录上传: fileName={}, size={}, sessionId={}",
                       userId, file.getOriginalFilename(), file.getSize(), sessionId);

            // 验证文件
            if (file.isEmpty()) {
                return ResponseEntity.badRequest()
                        .body(ApiResponse.error("文件不能为空"));
            }

            // 上传文件（带传输记录）
            FileInfo fileInfo = fileManagementService.uploadFileWithTransfer(userId, file, parentId, sessionId);

            logger.info("带传输记录上传成功: fileId={}, fileName={}",
                       fileInfo.getId(), fileInfo.getOriginalName());

            return ResponseEntity.ok(ApiResponse.success(FileInfoDTO.from(fileInfo)));

        } catch (Exception e) {
            logger.error("带传输记录上传失败", e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                    .body(ApiResponse.error("上传失败: " + e.getMessage()));
        }
    }
    
    // 私有验证方法
    
    private void validateUploadInitRequest(UploadInitRequest request) {
        if (request.getFileName() == null || request.getFileName().trim().isEmpty()) {
            throw new IllegalArgumentException("文件名不能为空");
        }
        
        if (request.getFileSize() == null || request.getFileSize() <= 0) {
            throw new IllegalArgumentException("文件大小必须大于0");
        }
        
        if (request.getFileSha256() == null || request.getFileSha256().length() != 64) {
            throw new IllegalArgumentException("文件SHA256哈希格式错误");
        }
        
        if (request.getChunkSize() == null || request.getChunkSize() <= 0) {
            throw new IllegalArgumentException("分片大小必须大于0");
        }
        
        // 检查文件大小限制（1GB）
        if (request.getFileSize() > 1024 * 1024 * 1024L) {
            throw new IllegalArgumentException("文件大小不能超过1GB");
        }
    }
    
    private void validateChunkUpload(String uploadId, Integer chunkIndex, 
                                   MultipartFile chunk, String chunkMd5) {
        if (uploadId == null || uploadId.trim().isEmpty()) {
            throw new IllegalArgumentException("上传会话ID不能为空");
        }
        
        if (chunkIndex == null || chunkIndex < 0) {
            throw new IllegalArgumentException("分片索引无效");
        }
        
        if (chunk == null || chunk.isEmpty()) {
            throw new IllegalArgumentException("分片文件不能为空");
        }
        
        if (chunkMd5 == null || chunkMd5.length() != 32) {
            throw new IllegalArgumentException("分片MD5哈希格式错误");
        }
        
        // 检查分片大小限制（10MB）
        if (chunk.getSize() > 10 * 1024 * 1024L) {
            throw new IllegalArgumentException("分片大小不能超过10MB");
        }
    }
    
    private void validateMergeRequest(MergeChunksRequest request) {
        if (request.getUploadId() == null || request.getUploadId().trim().isEmpty()) {
            throw new IllegalArgumentException("上传会话ID不能为空");
        }
        
        if (request.getFileName() == null || request.getFileName().trim().isEmpty()) {
            throw new IllegalArgumentException("文件名不能为空");
        }
    }
}
